package icu.zhhll.lang;

import icu.zhhll.lang.runtime.CPUCores;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 业务线程池
 * <p>
 * 相同业务共用一个线程池
 *
 * @author zh
 * @date 2023/8/13 21:53
 */
public class ThreadPools {
    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPools.class);
    // 线程池中核心线程数的最大值
//    private static final int CORE_POOL_SIZE = 4;
    // 线程池中能拥有最多线程数
    private static final int MAX_POOL_SIZE = CPUCores.processors * 2;
    // 核心线程数
    private static final int CORE_SIZE = CPUCores.processors;
    // 用于缓存任务的阻塞队列
    private static final int WORK_QUEUE_SIZE = 200;
    // 线程池维护线程所允许的空闲时间
    private static final int KEEP_ALIVE_TIME = 600;


    private final ExecutorService exec;
    private final String bizName;

    private ThreadPools(String bizName) {
        this.bizName = bizName;
        BizThreadFactory bizThreadFactory = new BizThreadFactory(bizName);
        exec = new ThreadPoolExecutor(CORE_SIZE, MAX_POOL_SIZE,
                KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue<>(WORK_QUEUE_SIZE), bizThreadFactory,
                new ThreadPoolExecutor.CallerRunsPolicy());
        // 允许核心线程回收
        ((ThreadPoolExecutor) (exec)).allowCoreThreadTimeOut(true);
    }


    public void exec(Runnable task) {
        LOGGER.debug("{}提交任务，线程池为{}", bizName, exec);
        exec.submit(task);
    }

    public <T> Future<T> exec(Callable<T> task) {
        LOGGER.debug("{}提交任务，线程池为{}", bizName, exec);
        return exec.submit(task);
    }

    /**
     * 打印线程情况
     */
    public static void report() {
        Map<String, ThreadPools> bizList = Factory.BIZ_LIST;
        if (bizList.size() > 0) {
            for (Map.Entry<String, ThreadPools> entry : bizList.entrySet()) {
                ThreadPools threadPools = entry.getValue();
                ThreadPoolExecutor curExecutor;
                if (threadPools != null && (curExecutor = (ThreadPoolExecutor) threadPools.exec) != null) {
                    LOGGER.info("{}线程池 {}", entry.getKey(), curExecutor);
                }

            }
        }
    }

    public static class Factory {
        // 默认业务
        private static final String DEFAULT_BIZ = "default";
        // 业务集合
        private static final Map<String, ThreadPools> BIZ_LIST = new ConcurrentHashMap<>();

        public static ThreadPools getInstance() {
            return getInstance(DEFAULT_BIZ);
        }


        public static ThreadPools getInstance(String bizName) {
            ThreadPools cachedThreadPools = BIZ_LIST.get(bizName);
            if (cachedThreadPools != null) {
                return cachedThreadPools;
            }
            synchronized (ThreadPools.class) {
                if (!BIZ_LIST.containsKey(bizName)) { // 防止重复创建
                    ThreadPools pools = new ThreadPools(bizName);
                    BIZ_LIST.put(bizName, pools);
                    LOGGER.debug("创建线程池{}", bizName);
                }
            }

            return BIZ_LIST.get(bizName);
        }
    }

    /**
     * 业务线程工厂
     */
    private static class BizThreadFactory implements ThreadFactory {

        private final AtomicInteger threadNumber;
        private final String prefixName;

        public BizThreadFactory(String bizName) {
            threadNumber = new AtomicInteger(1);
            this.prefixName = bizName + "-ThreadId-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r, prefixName + threadNumber.getAndIncrement());
            thread.setDaemon(true);
            return thread;
        }
    }

}
